/*
 Автор: Швейкин Евгений Юрьевич

 Функциональное описание:     
    Модуль упрощает шину авалон до сигналов адреса, данных и подтверждений
*/
//--------------------------------------------------------------------------------------------------
// Описание структуры порта канала FC

// *********************** НАЧАЛО МОДУЛЯ ***********************************************************
module ctrl_avs
#(
    parameter int               wdt_p = 32'd100
)
(
    input  logic                                reset_n,
    input  logic                                clk,
    
    // Управление модулем
    input  logic [31:0]                         avs_address,
    input  logic [9:0]                          avs_burstcount,
    input  logic                                avs_beginbursttransfer,
    input  logic                                avs_write,
    input  logic [31:0]                         avs_writedata,

    input  logic                                avs_read,
    output logic [31:0]                         avs_readdata,
    output logic                                avs_readdatavalid,
    
    output logic                                avs_waitrequest,
   
    output logic                                rx_val,
    output logic [31:0]                         rx_data,
    
    output logic                                tx_req,
    input  logic                                tx_val,
    input  logic [31:0]                         tx_data,

    output logic [31:0]                         addr            // Адрес операции ч/з
);

// ********************** МАКРОСЫ ******************************************************************
    
//  ********************* КОНСТАНТЫ ****************************************************************
    
//  ********************* ФУНКЦИИ ******************************************************************

//  ********************* ТИПЫ ДАННЫХ **************************************************************
    

// ********************* ПЕРЕМЕННЫЕ ****************************************************************
    logic [9:0]         burstcount;
    logic [31:0]        wdt_cnt;
    logic               err;
// ********************* ИНИЦИАЛИЗАЦИЯ ПЕРЕМЕННЫХ ДЛЯ СИМУЛЯТОРА ***********************************

//  ********************* ASSIGN *******************************************************************
    assign rx_val           = avs_write & (~avs_beginbursttransfer);
    assign rx_data          = avs_writedata; 
        
    assign avs_readdata     = tx_data; 
                // Пока счетчик не обнулилися, будет 0
    assign avs_waitrequest = ~(|burstcount);
// ********************* ПРОЦЕССЫ ******************************************************************
    
    // Счетчик адресов пля шины управления
    always_ff @(posedge clk, negedge reset_n)
    begin
        if (!reset_n) begin
            // avs_waitrequest     <= 1'b1;
            burstcount          <= 10'd0;
        end
        else begin

            if (avs_beginbursttransfer) begin
                addr                <= avs_address;
                burstcount          <= avs_burstcount;
                // avs_waitrequest     <= 1'b0;
            end
            // else if (burstcount < 10'd1) begin
                // avs_waitrequest     <= 1'b1;
            // end
            else if (avs_write || avs_readdatavalid) begin
                addr                <= addr + 4'd1;
                burstcount          <= burstcount - 10'd1;
            end
            else;
        end
    end

    // Установка avs_readdatavalid только на количество тактов не более burstcount
    // Если на tx_req долго не будет ответа, чтение выставится автоматически
    always_ff @(posedge clk)
    begin
        // Только пока счетчик слов пачки не нулевой, можно ставить подтверждение чтения данных
        if (|burstcount) begin
            avs_readdatavalid  <= tx_val | err;
        end

        if (avs_read & (!avs_beginbursttransfer))
            tx_req  <= avs_read;
        else if (burstcount <= 10'd1) 
            tx_req  <= 1'b0;
        else;
    end
    
    // Сторожевой таймер. Для принудительного выхода из состояния ожидания данных при чтении.
    always_ff @(posedge clk)
    begin
        err     <= 1'b0;
        // Счетчик увеличиваем всегда. Когда он не нужен, обнулится.
        wdt_cnt <= wdt_cnt + 32'd1;
        if (tx_req | avs_waitrequest)
            wdt_cnt  <= 32'd0;
        else if (wdt_cnt >= wdt_p) begin
            err     <= 1'b1;
            wdt_cnt <= 32'd0;
        end
        else;
    end
// ********************* ПОДКЛЮЧАЕМЫЕ МОДУЛИ *******************************************************

endmodule 